#pragma once

#include "interface.hpp"
#include <algorithm>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <libusb-1.0/libusb.h>
#include <logger.hpp>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <usb.h>
#include <vector>

const std::string CH9326 = "ch9326";
const std::string CH9329 = "ch9329";

/*	BAUD rate setting	*/
#define B300    0x01
#define B600    0x02
#define B1200   0x03
#define B2400   0x04
#define B4800   0x05
#define B9600   0x06
#define B14400  0x07
#define B19200  0x08
#define B28800  0x09
#define B38400  0x0A
#define B57600  0x0B
#define B76800  0x0C
#define B115200 0x0D

const std::map<int, uint8_t> baudrateTable = {
    {300, B300},
    {600, B600},
    {1200, B1200},
    {2400, B2400},
    {4800, B4800},
    {9600, B9600},
    {14400, B14400},
    {19200, B19200},
    {28800, B28800},
    {38400, B38400},
    {57600, B57600},
    {76800, B76800},
    {115200, B115200},
}; /* 波特率对照表 */

/* Parity define	*/
#define P_ODD  0x01  // 奇校验
#define P_EVEN 0x02  // 偶校验
#define P_SPC  0x03  // 空白位
#define P_NONE 0x04  // 无校验

const std::map<std::string, uint8_t> parityTable = {
    {"o", P_ODD},
    {"O", P_ODD},
    {"e", P_EVEN},
    {"E", P_EVEN},
    {"n", P_NONE},
    {"N", P_NONE},
}; /* 校验位对照表 */

/*	Data bits define		*/
#define BIT_5 0x01
#define BIT_6 0x02
#define BIT_7 0x03
#define BIT_8 0x04

const std::map<int, uint8_t> dataBitsTable = {
    {5, BIT_5},
    {6, BIT_6},
    {7, BIT_7},
    {8, BIT_8},
}; /* 数据位对照表 */

/* Stop bits define	*/
#define STOP_1 0x01
#define STOP_2 0x02

const std::map<int, uint8_t> stopBitsTable = {
    {1, STOP_1},
    {2, STOP_2},
};

#define U8_TO_U16(a, b) ((((uint16_t)a) << 8) | ((uint16_t)b))

#define MAX_DEVICES    0x10
#define HID_RT_INPUT   0x01
#define HID_RT_OUTPUT  0x02
#define HID_REPORT_GET 0x01
#define HID_REPORT_SET 0x09

#define ERROR_CHECK(condition, ...) \
    if (condition) {                \
        printf(__VA_ARGS__);        \
        return false;               \
    }

class ModbusPacket {
public:
    enum FunCode_t : uint8_t {
        READ_REG = 0x03,
        WRITE_REG = 0x06,
    };

public:
    ModbusPacket() = default;
    ~ModbusPacket() = default;

    static std::vector<uint8_t> readRegisterPack(uint8_t slaveAddr, uint16_t regAddr)
    {
        std::vector<uint8_t> pack;
        pack.emplace_back(slaveAddr);
        pack.emplace_back(READ_REG);
        pack.emplace_back(regAddr >> 8 & 0xff);
        pack.emplace_back(regAddr & 0xff);
        pack.emplace_back(0x00);
        pack.emplace_back(0x01);
        getCrc16(pack);
        return pack;
    }

    static std::vector<uint8_t> readMultRegisterPack(uint8_t slaveAddr, uint8_t readFunc, uint16_t regAddr, uint16_t regLen)
    {
        std::vector<uint8_t> pack;
        pack.emplace_back(slaveAddr);
        pack.emplace_back(readFunc);

        if (readFunc != 0x11) { /* 需要特殊处理 */
            pack.emplace_back(regAddr >> 8 & 0xff);
            pack.emplace_back(regAddr & 0xff);
            pack.emplace_back(regLen >> 8 & 0xff);
            pack.emplace_back(regLen & 0xff);
        }

        getCrc16(pack);
        return pack;
    }

    static std::vector<uint8_t> writeMultRegisterPack(uint8_t slaveAddr, uint8_t writeFunc, uint16_t regAddr, uint16_t regLen, const std::vector<uint8_t> &data)
    {
        std::vector<uint8_t> pack;
        pack.emplace_back(slaveAddr);
        pack.emplace_back(writeFunc);

        if (writeFunc == 0x06) {
            pack.emplace_back(regAddr >> 8 & 0xff);
            pack.emplace_back(regAddr & 0xff);

            for (const auto &item : data) {
                pack.emplace_back(item);
            }
        } else if (writeFunc == 0x10) {
            pack.emplace_back(regAddr >> 8 & 0xff);
            pack.emplace_back(regAddr & 0xff);

            pack.emplace_back(regLen >> 8 & 0xff);
            pack.emplace_back(regLen & 0xff);
            pack.emplace_back(static_cast<uint8_t>(data.size()));

            for (const auto &item : data) {
                pack.emplace_back(item);
            }
        }

        getCrc16(pack);

        return pack;
    }

    static std::vector<uint8_t> writeRegisterPack(uint8_t slaveAddr, uint16_t regAddr, uint16_t val)
    {
        std::vector<uint8_t> pack;
        pack.emplace_back(slaveAddr);
        pack.emplace_back(WRITE_REG);
        pack.emplace_back(regAddr >> 8 & 0xff);
        pack.emplace_back(regAddr & 0xff);
        pack.emplace_back(val >> 8 & 0xff);
        pack.emplace_back(val & 0xff);
        getCrc16(pack);
        return pack;
    }

    static bool checkCrc(std::vector<uint8_t> arr)
    {
        auto crc = U8_TO_U16(arr[arr.size() - 2], arr[arr.size() - 1]);
        arr.pop_back();
        arr.pop_back();
        return getCrc16(arr) == crc;
    }

private:
    static uint16_t getCrc16(std::vector<uint8_t> &arr)
    {
        uint16_t crc = 0xFFFF;
        std::size_t length = arr.size();

        for (std::size_t i = 0; i < length; ++i) {
            crc ^= arr[i];
            for (std::size_t j = 0; j < 8; ++j) {
                if (crc & 0x0001) {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }

        // arr.emplace_back(crc >> 8 & 0xff);
        // arr.emplace_back(crc & 0xff);
        arr.emplace_back(crc & 0xff);
        arr.emplace_back(crc >> 8 & 0xff);

        return crc;
    }
};

struct UsbDevice_t {
    libusb_context *ctx;          /* usb上下文 */
    struct libusb_device *dev;    /* 设备 */
    libusb_device_handle *handle; /* 句柄 */
    int outEndPoint;              /* 输出端点 */
    int inEndPoint;               /* 输入端点 */
    uint8_t slaveAddr;            /* modbus地址 */
    uint8_t dataBits;             /* 数据位 */
    uint8_t baudrate;             /* 波特率 */
    uint8_t parity;               /* 校验位 */
    uint8_t stopBits;             /* 停止位 */
    std::string model;            /* 设备型号 */
    std::string profilePath;      /* 点表文件路径 */
    uint32_t readTimeout;         /* 读超时 */
    uint32_t writeTimeout;        /* 写超时 */
    std::string devModel;         /* 型号 ch9326 - ch9329 */

    UsbDevice_t()
    {
        ctx = nullptr;
        dev = nullptr;
        handle = nullptr;
        outEndPoint = inEndPoint = 0;
        slaveAddr = 0x03;
        readTimeout = 2000;
        writeTimeout = 1000;
    }

    bool isOpen(void)
    {
        return handle != nullptr;
    }

    bool close(void)
    {
        dev = nullptr;
        handle = nullptr;
        return true;
    }

    bool isFind(void)
    {
        return dev != nullptr;
    }
};

class UsbInterface : public Interface {
private:
    UsbDevice_t _usbDevice;

private:
    static std::function<bool(void)> onUsbExit;

private:
    bool setTransmitParam(uint8_t baudrate, uint8_t dataBits, uint8_t parity, uint8_t stopBits, uint8_t interval = 30);

    static int hotplug_callback(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data);

public:
    UsbInterface();

    ~UsbInterface();

    bool findUsbDevice(int vid, int pid);

    bool isFindDev(void);

    bool openUsbDevice(void);

    bool write(const std::vector<uint8_t> &data) override;

    std::vector<uint8_t> read(void) override;

    bool readPoint(const std::string &pointName) override;

    bool writePoint(const std::string &pointName, uint32_t value) override;

    std::vector<uint8_t> transmit(const std::vector<uint8_t> &data) override;

    UsbInterface &setBaudrate(int baudrate);

    UsbInterface &setParity(const std::string &parity);

    UsbInterface &setDataBits(int dataBits);

    UsbInterface &setStopBits(int stopBits);

    UsbInterface &setSlaveAddr(int slaveAddr);

    bool closeUsbDevice(void);

    template <typename T>
    void printBuff(const std::vector<T> &buff, const std::string &tag)
    {
        std::ostringstream oss;

        oss << (tag + ((tag.find(":") != std::string::npos) ? "" : ":"));
        if (tag.find("recv") != std::string::npos) {
            // for (int i = 0; i < buff.size(); i++) {
            //     if (i && !(i % 16)) {
            //         ::printf("\n");
            //     }
            //     ::printf("<%02x>", buff[i]);
            // }

            for (const auto &item : buff) {
                oss << "<" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(item) << ">";
            }

        } else if (tag.find("send") != std::string::npos) {
            // for (int i = 0; i < buff.size(); i++) {
            //     if (i && !(i % 16)) {
            //         ::printf("\n");
            //     }
            //     ::printf("[%02x]", buff[i]);
            // }

            for (const auto &item : buff) {
                oss << "[" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(item) << "]";
            }

        } else {
            // for (int i = 0; i < buff.size(); i++) {
            //     if (i && !(i % 16)) {
            //         ::printf("\n");
            //     }
            //     ::printf("{%02x}", buff[i]);
            // }
            for (const auto &item : buff) {
                oss << "{" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(item) << "}";
            }
        }
        // ::printf("\n");
        information("{}", oss.str());
    }

    void registerOnUsbExit(const std::function<bool(void)> &func);
};

std::function<bool(void)> UsbInterface::onUsbExit;

void UsbInterface::registerOnUsbExit(const std::function<bool(void)> &func)
{
    onUsbExit = func;
}

bool UsbInterface::closeUsbDevice(void)
{
    if (!_usbDevice.isOpen()) {
        error("usb device not open");
        return false;
    }

    libusb_release_interface(_usbDevice.handle, 0);
    libusb_close(_usbDevice.handle);

    return _usbDevice.close();
}

UsbInterface::UsbInterface()
{
    auto ret = libusb_init(&_usbDevice.ctx);
    if (LIBUSB_SUCCESS != ret) {
        error("libusb initialization failed: {}", ret);
        return;
    }

    std::thread([&]() {
        libusb_hotplug_callback_handle handle;
        ret = libusb_hotplug_register_callback(_usbDevice.ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, this, &handle);
        if (ret != LIBUSB_SUCCESS) {
            error("usb register insert callback failed");
        }

        ret = libusb_hotplug_register_callback(_usbDevice.ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, this, &handle);
        if (ret != LIBUSB_SUCCESS) {
            error("usb register exit callback failed");
        }

        while (true) {
            libusb_handle_events_completed(_usbDevice.ctx, NULL);
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }).detach();
}

UsbInterface::~UsbInterface()
{
    if (_usbDevice.ctx) {
        libusb_exit(_usbDevice.ctx);
    }
}

bool UsbInterface::findUsbDevice(int vid, int pid)
{
    libusb_device *dev = nullptr;
    libusb_device **devs = nullptr;

    std::size_t i = 0;

    auto cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0) {
        information("failed get device list");
        return false;
    } else if (0 == cnt) {
        information("can't find usb device");
        return false;
    }

    while (nullptr != (dev = devs[i++])) {
        struct libusb_device_descriptor desc;
        auto ret = libusb_get_device_descriptor(dev, &desc);
        if (ret < 0) {
            error("failed to get device descriptor");
            libusb_free_device_list(devs, 1);
            return false;
        }

        if ((desc.idProduct != pid) || (desc.idVendor != vid)) {
            continue;
        }

        this->_usbDevice.dev = dev;
        if (vid == 0x1A86 && pid == 0xe010) {
            this->_usbDevice.inEndPoint = 0x82;
            this->_usbDevice.outEndPoint = 0x02;
            this->_usbDevice.devModel = CH9326;
        } else {
            this->_usbDevice.inEndPoint = 0x84;
            this->_usbDevice.outEndPoint = 0x04;
            this->_usbDevice.devModel = CH9329;
        }

        libusb_free_device_list(devs, 1);
        return true;
    }

    libusb_free_device_list(devs, 1);
    return false;
}

bool UsbInterface::isFindDev(void)
{
    return _usbDevice.isFind();
}

bool UsbInterface::openUsbDevice(void)
{
    if (!_usbDevice.dev) {
        error("can't open usbDevice");
        return false;
    }

    auto ret = libusb_open(_usbDevice.dev, &_usbDevice.handle);
    if (LIBUSB_SUCCESS != ret) {
        error("failed open usbDevice");
        return false;
    }

    libusb_config_descriptor *config_desc = nullptr;
    auto result = libusb_get_active_config_descriptor(_usbDevice.dev, &config_desc);
    if (result != LIBUSB_SUCCESS) {
        error("Failed to get active configuration descriptor");
        libusb_close(_usbDevice.handle);
        return false;
    }

    // 遍历接口和端点
    for (int i = 0; i < config_desc->bNumInterfaces; ++i) {
        const libusb_interface *interface = &(config_desc->interface[i]);
        for (int j = 0; j < interface->num_altsetting; ++j) {
            const libusb_interface_descriptor *interface_desc = &(interface->altsetting[j]);

            // 检查接口是否是 HID 类型的接口
            if (interface_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
                // 遍历端点
                for (int k = 0; k < interface_desc->bNumEndpoints; ++k) {
                    const libusb_endpoint_descriptor *endpoint_desc = &(interface_desc->endpoint[k]);

                    // 判断端点的方向和类型
                    if ((endpoint_desc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
                        (endpoint_desc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) {
                        // 输入端点
                        information("Input Endpoint: {}", static_cast<int>(endpoint_desc->bEndpointAddress));
                    } else if ((endpoint_desc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
                               (endpoint_desc->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
                        // 输出端点
                        information("Output Endpoint: {}", static_cast<int>(endpoint_desc->bEndpointAddress));
                    }
                }
            }
        }
    }

    // 释放配置描述符内存
    libusb_free_config_descriptor(config_desc);

    libusb_detach_kernel_driver(_usbDevice.handle, 0);
    libusb_claim_interface(_usbDevice.handle, 0);

    return setTransmitParam(_usbDevice.baudrate, _usbDevice.dataBits, _usbDevice.parity, _usbDevice.stopBits);
}

bool UsbInterface::setTransmitParam(uint8_t baudrate, uint8_t dataBits, uint8_t parity, uint8_t stopBits, uint8_t interval)
{
    ERROR_CHECK(baudrate > B115200 || baudrate < B300, "baudrate error\n");
    ERROR_CHECK(parity > P_NONE || parity < P_ODD, "parity error\n");
    ERROR_CHECK(stopBits > STOP_2 || stopBits < STOP_1, "stopBits error\n");
    ERROR_CHECK(dataBits > BIT_8 || dataBits < BIT_5, "dataBits error\n");

    char buf[32] = {0};
    char m_str[5] = {0};

    m_str[4] = interval;
    m_str[0] |= 0x01;

    switch (baudrate) {
        case B300:
            m_str[2] = 0x80;
            m_str[3] = 0xD9;
            break;
        case B600:
            m_str[2] = 0x81;
            m_str[3] = 0x64;
            break;
        case B1200:
            m_str[2] = 0x81;
            m_str[3] = 0xB2;
            break;
        case B2400:
            m_str[2] = 0x81;
            m_str[3] = 0xD9;
            break;
        case B4800:
            m_str[2] = 0x82;
            m_str[3] = 0x64;
            break;
        case B9600:
            m_str[2] = 0x82;
            m_str[3] = 0xB2;
            break;
        case B14400:
            m_str[2] = 0x82;
            m_str[3] = 0xCC;
            break;
        case B19200:
            m_str[2] = 0x82;
            m_str[3] = 0xD9;
            break;
        case B28800:
            m_str[2] = 0x83;
            m_str[3] = 0x30;
            break;
        case B38400:
            m_str[2] = 0x83;
            m_str[3] = 0x64;
            break;
        case B57600:
            m_str[2] = 0x83;
            m_str[3] = 0x98;
            break;
        case B76800:
            m_str[2] = 0x83;
            m_str[3] = 0xB2;
            break;
        case B115200:
            m_str[2] = 0x83;
            m_str[3] = 0xCC;
            break;
        default:
            m_str[2] = 0x82;
            m_str[3] = 0xCC;
            break;
    }

    switch (parity) {
        case P_ODD:
            m_str[1] &= ~0x30;
            m_str[1] |= 0x08;
            break;
        case P_EVEN:
            m_str[1] &= ~0x10;
            m_str[1] |= 0x18;
            break;
        case P_SPC:
            m_str[1] |= 0x38;
            break;
        case P_NONE:
            m_str[1] &= ~0x08;
            break;
        default:
            m_str[1] &= ~0x08;
            break;
    }

    switch (stopBits) {
        case STOP_1:
            m_str[1] |= 0x04;
            break;
        case STOP_2:
            m_str[1] &= ~0x04;
            break;
        default:
            m_str[1] |= 0x04;
            break;
    }

    switch (dataBits) {
        case BIT_5:
            m_str[1] &= ~0x3;
            break;
        case BIT_6:
            m_str[1] &= ~0x3;
            m_str[1] |= 0x1;
            break;
        case BIT_7:
            m_str[1] &= ~0x3;
            m_str[1] |= 0x2;
            break;
        case BIT_8:
            m_str[1] |= 0x3;
            break;

        default:
            break;
    }

    m_str[0] = 0xFF;
    m_str[1] |= 0xC0;

    memcpy(buf, m_str, sizeof(m_str));

    return libusb_control_transfer(_usbDevice.handle,
                                   LIBUSB_ENDPOINT_OUT + LIBUSB_REQUEST_TYPE_CLASS + LIBUSB_RECIPIENT_INTERFACE,
                                   HID_REPORT_SET,
                                   HID_RT_OUTPUT << 8,
                                   0x00,
                                   (unsigned char *)buf,
                                   sizeof(buf),
                                   _usbDevice.writeTimeout) == sizeof(buf);
}

bool UsbInterface::write(const std::vector<uint8_t> &data)
{
    if (!_usbDevice.isOpen()) {
        error("usb device not open, func : {}, line : {}", __func__, __LINE__);
        return false;
    }

    std::size_t packCount = data.size() / 31;
    std::size_t left = data.size() % 31;

    std::size_t sendBytes = 0;

    for (int i = 0; i < packCount; i++) {
        int len = 0;
        std::vector<uint8_t> pack({31});
        pack.insert(pack.end(), data.begin() + sendBytes, data.begin() + sendBytes + 31);

        auto ret = libusb_interrupt_transfer(_usbDevice.handle,
                                             _usbDevice.outEndPoint,
                                             pack.data(),
                                             pack.size(),
                                             &len,
                                             _usbDevice.writeTimeout);

        if (ret == -ETIMEDOUT || len != 32) {
            error("send error");
            return false;
        }
        sendBytes += len - 1;
    }

    if (left) {
        int len = 0;
        std::vector<uint8_t> pack({static_cast<uint8_t>(left)});
        pack.insert(pack.end(), data.begin() + sendBytes, data.end());

        auto r = libusb_interrupt_transfer(_usbDevice.handle,
                                           _usbDevice.outEndPoint,
                                           pack.data(),
                                           pack.size(),
                                           &len,
                                           _usbDevice.writeTimeout);

        if (r == -ETIMEDOUT || len != left + 1) {
            return false;
        }
        sendBytes += len - 1;
    }

    printBuff(data, "usb send:");

    return sendBytes == data.size();
}

std::vector<uint8_t> UsbInterface::read(void)
{
    std::vector<uint8_t> recvData;
    if (!_usbDevice.isOpen()) {
        error("usb device not open");
        return recvData;
    }

    int size = 64;

    if (_usbDevice.devModel == CH9326) {
        size = 32;
    }

    auto buf = std::make_unique<unsigned char[]>(size);

    int len = 0;

    auto ret = libusb_interrupt_transfer(_usbDevice.handle,
                                         _usbDevice.inEndPoint,
                                         buf.get(),
                                         size,
                                         &len,
                                         _usbDevice.readTimeout);
    if (ret != LIBUSB_SUCCESS || len == 0) {
        error("can't recv some data, ret = {}, len = {}, endpoint = {}", ret, len, _usbDevice.inEndPoint);
        return recvData;
    }

    if (len) {
        for (int i = 1; i <= buf[0]; i++) {
            recvData.push_back(buf[i]);
        }
    }

    printBuff(recvData, "usb recv:");

    return recvData;
}

UsbInterface &UsbInterface::setBaudrate(int baudrate)
{
    if (baudrateTable.find(baudrate) != baudrateTable.end()) {
        _usbDevice.baudrate = baudrateTable.at(baudrate);
    }

    return *this;
}

UsbInterface &UsbInterface::setParity(const std::string &parity)
{
    if (parityTable.find(parity) != parityTable.end()) {
        _usbDevice.parity = parityTable.at(parity);
    }

    return *this;
}

UsbInterface &UsbInterface::setDataBits(int dataBits)
{
    if (dataBitsTable.find(dataBits) != dataBitsTable.end()) {
        _usbDevice.dataBits = dataBitsTable.at(dataBits);
    }

    return *this;
}

UsbInterface &UsbInterface::setStopBits(int stopBits)
{
    if (stopBitsTable.find(stopBits) != stopBitsTable.end()) {
        _usbDevice.stopBits = stopBitsTable.at(stopBits);
    }

    return *this;
}

UsbInterface &UsbInterface::setSlaveAddr(int slaveAddr)
{
    _usbDevice.slaveAddr = slaveAddr;
    return *this;
}

std::vector<uint8_t> UsbInterface::transmit(const std::vector<uint8_t> &data)
{
    if (!write(data)) {
        return std::vector<uint8_t>();
    }

    return read();
}

bool UsbInterface::readPoint(const std::string &pointName)
{
    auto points = findPointByName(pointName);

    information("points size is {}", points.size());
    if (!points.size()) {
        return false;
    }

    information("point name is {}", pointName);
    for (auto &item : points) {
        auto rx = transmit(ModbusPacket::readMultRegisterPack(_usbDevice.slaveAddr, item->second.readFunc, item->second.addr, item->second.len));

        if (!rx.size() || rx.size() < 4) {
            item->second.operaFail();
            continue;
        }

        if (rx[0] != _usbDevice.slaveAddr) {
            item->second.operaFail();
            continue;
        }

        if (rx[1] != item->second.readFunc) {
            item->second.operaFail();
            continue;
        }

        uint32_t value = 0;

        if (item->second.type == "uint16") {
            for (int i = 0; i < rx[2]; i++) {
                value |= rx[3 + i];
                if (i != rx[2] - 1) {
                    value <<= 8;
                }
            }
        } else if (item->second.type == "string") {
            std::string cString;
            for (int i = 0; i < rx[2]; i++) {
                cString += std::to_string(rx[3 + i]);
            }
            item->second.rString = cString;
        } else if (item->second.type == "BCD") {
            std::ostringstream oss;
            for (int i = 0; i < rx[2]; i++) {
                oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(rx[3 + i]);
            }

            item->second.rString = oss.str();
        }

        item->second.rawValue = value;

        if (item->second.bitMap.first != -1 && item->second.bitMap.second != -1) {
            item->second.rValue = getBitsValue(value, item->second.bitMap.first, item->second.bitMap.second);
        } else {
            item->second.rValue = value;
        }

        item->second.operaSuccess();
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    return true;
}

bool UsbInterface::writePoint(const std::string &pointName, uint32_t value)
{
    auto points = findPointByName(pointName);
    if (points.size() != 1) {
        return false;
    }

    for (auto &item : points) {
        information("write point name : {}", pointName);
        std::vector<uint8_t> rx;

        if (item->second.bitMap.first != -1 && item->second.bitMap.second != -1) {
            if (item->second.readFunc) {
                readPoint(item->first);

                if (item->second.operationResult()) {
                    auto mask = getMask(item->second.bitMap.first, item->second.bitMap.second);

                    auto num = item->second.rawValue & (~mask);
                    value = num | (value << item->second.bitMap.first);
                }
            }
        }

        if (item->second.len == 1) {
            rx = transmit(ModbusPacket::writeMultRegisterPack(_usbDevice.slaveAddr, item->second.writeFunc, item->second.addr, item->second.len, {static_cast<uint8_t>(value >> 8 & 0xff), static_cast<uint8_t>(value & 0xff)}));
        } else if (item->second.len == 2) {
            rx = transmit(ModbusPacket::writeMultRegisterPack(_usbDevice.slaveAddr, item->second.writeFunc, item->second.addr, item->second.len, {static_cast<uint8_t>(value >> 24 & 0xff), static_cast<uint8_t>(value >> 16 & 0xff), static_cast<uint8_t>(value >> 8 & 0xff), static_cast<uint8_t>(value & 0xff)}));
        }

        if (!rx.size() || rx.size() < 4) {
            item->second.operaFail();
            continue;
        }

        if (rx[0] != _usbDevice.slaveAddr) {
            item->second.operaFail();
            continue;
        }

        if (rx[1] != item->second.writeFunc) {
            item->second.operaFail();
            continue;
        }

        item->second.wValue = value;
        item->second.operaSuccess();
    }

    return true;
}

int UsbInterface::hotplug_callback(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data)
{
    libusb_device_descriptor desc;
    libusb_get_device_descriptor(device, &desc);

    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
        information("USB device inserted:");
        information("  Vendor ID: {}", desc.idVendor);
        information("  Product ID: {}", desc.idProduct);
        information("  Device Class: {}", desc.bDeviceClass);
    } else {
        information("USB device exit:");
        information("  Vendor ID: {}", desc.idVendor);
        information("  Product ID: {}", desc.idProduct);
        information("  Device Class: {}", desc.bDeviceClass);

        if (desc.idVendor == 0x1A86 && desc.idProduct == 0xe010) {
            if (onUsbExit) {
                onUsbExit();
            }
        } else if (desc.idVendor == 0x1A86 && desc.idProduct == 0xe429) {
            if (onUsbExit) {
                onUsbExit();
            }
        }
    }
    return 0;
}